package com.csot.ry.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.csot.common.utils.SecurityUtils;
import com.csot.model.CitySegment;
import com.csot.ry.domain.TCityIp;
import com.csot.ry.domain.TDetectJob;
import com.csot.ry.domain.TDetectJobSegment;
import com.csot.ry.mapper.TCityIpMapper;
import com.csot.ry.mapper.TDetectJobMapper;
import com.csot.ry.service.ITDetectJobService;
import com.csot.ry.util.UserUtils;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.csot.common.exception.ServiceException;
import com.csot.common.utils.DateUtils;
import com.csot.common.utils.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 探活Service业务层处理
 *
 * @author 刘沙
 * @date 2022-06-15
 */
@Service
public class TDetectJobServiceImpl implements ITDetectJobService {
    @Autowired
    private TDetectJobMapper tDetectJobMapper;
    @Autowired
    private TCityIpMapper tCityIpMapper;

    @Value("${job.address}")
    private String jobAddress;

    /**
     * 查询探活
     *
     * @param id 探活主键
     * @return 探活
     */
    @Override
    public TDetectJob selectTDetectJobById(Long id) {
        return tDetectJobMapper.selectTDetectJobById(id);
    }

    /**
     * 查询探活列表
     *
     * @param tDetectJob 探活
     * @return 探活
     */
    @Override
    public List<TDetectJob> selectTDetectJobList(TDetectJob tDetectJob) {
        return tDetectJobMapper.selectTDetectJobList(tDetectJob);
    }

    /**
     * 新增探活
     *
     * @param tDetectJob 探活
     * @return 结果
     */
    @Transactional
    @Override
    public int insertTDetectJob(TDetectJob tDetectJob) {
        tDetectJob.setCreateTime(DateUtils.getNowDate());
        int rows = tDetectJobMapper.insertTDetectJob(tDetectJob);
        insertTDetectJobSegment(tDetectJob);
        return rows;
    }

    /**
     * 修改探活
     *
     * @param tDetectJob 探活
     * @return 结果
     */
    @Transactional
    @Override
    public int updateTDetectJob(TDetectJob tDetectJob) {
        tDetectJob.setUpdateTime(DateUtils.getNowDate());
        tDetectJobMapper.deleteTDetectJobSegmentByJobId(tDetectJob.getId());
        insertTDetectJobSegment(tDetectJob);
        return tDetectJobMapper.updateTDetectJob(tDetectJob);
    }

    /**
     * 批量删除探活
     *
     * @param ids 需要删除的探活主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteTDetectJobByIds(Long[] ids) {
        tDetectJobMapper.deleteTDetectJobSegmentByJobIds(ids);
        return tDetectJobMapper.deleteTDetectJobByIds(ids);
    }

    /**
     * 停止探活信息
     *
     * @param id 探活主键
     * @return 结果
     */
    @Transactional
    @Override
    public int stopTDetectJobById(Long id) {
        Db.update("UPDATE t_detect_job SET job_status = 'off',job_end=? WHERE id = ?", new Date(), id);
        JSONObject reqJjson = JSONUtil.createObj().put("job_id", id);
        try {
            String res = HttpUtil.post(jobAddress + "/stop", JSONUtil.parseObj(reqJjson));
            JSONObject resJson = JSONUtil.parseObj(res);
            return resJson.getInt("code");
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("网络无法连接");
        }
    }

    /**
     * 新增探活子表信息
     *
     * @param tDetectJob 探活对象
     */
    public void insertTDetectJobSegment(TDetectJob tDetectJob) {
        List<TDetectJobSegment> tDetectJobSegmentList = tDetectJob.getTDetectJobSegmentList();
        Long id = tDetectJob.getId();
        if (StringUtils.isNotNull(tDetectJobSegmentList)) {
            List<TDetectJobSegment> list = new ArrayList<TDetectJobSegment>();
            for (TDetectJobSegment tDetectJobSegment : tDetectJobSegmentList) {
                tDetectJobSegment.setJobId(id);
                list.add(tDetectJobSegment);
            }
            if (list.size() > 0) {
                tDetectJobMapper.batchTDetectJobSegment(list);
            }
        }
    }

    /**
     * 批量执行探活
     *
     * @param ids 需要执行探活主键集合
     * @return 结果
     */
    @Transactional
    @Override
    public int JobByIds(Long[] ids) {
        if (ids.length < 1) {
            throw new ServiceException("请选择要执行IP段");
        }
        CitySegment dao = new CitySegment().dao();

        Record record = Db.findFirst("select 1 from t_detect_job where job_status = 'on'");
        if (record != null) {
            throw new IllegalArgumentException("探活任务正在执行，不能重复执行！");
        }

        List<CitySegment> csList = dao
                .find("select * from t_city_segment where id in (" + ArrayUtil.join(ids, ",") + ")");

        TDetectJob tDetectJob = getTDetectJob(csList);
        tDetectJob.setCreateName(SecurityUtils.getUsername());
        this.insertTDetectJob(tDetectJob);
        List<TDetectJobSegment> tDetectJobSegmentList = new ArrayList<>();
        List<String> ips = new ArrayList<>();

        for (CitySegment cs : csList) {
            TCityIp tCityIp = new TCityIp();
            tCityIp.setIpJobId(tDetectJob.getId());
            tCityIp.setIpJobNo(tDetectJob.getJobNo());
            tCityIp.setIpSegmentId(cs.getId());
            tCityIpMapper.updateTCityIpByJob(tCityIp);

            TDetectJobSegment tDetectJobSegment = new TDetectJobSegment();
            BeanUtils.copyProperties(cs, tDetectJobSegment, "id");
            tDetectJobSegment.setJobId(tDetectJob.getId());
            tDetectJobSegmentList.add(tDetectJobSegment);

            ips.add(cs.getIpStartI() + "-" + cs.getIpEndI());
        }
        tDetectJob.setTDetectJobSegmentList(tDetectJobSegmentList);
        int i = this.updateTDetectJob(tDetectJob);

        // 转发给任务
        // 调用接口，传入ips
        String msg = startTask(tDetectJob.getId(), ips);
        if (!msg.contains("200")) {
            tDetectJob.setJobStatus("off");
            this.updateTDetectJob(tDetectJob);
//			throw new ServiceException("未成功！");
        }
        return i;
    }

    // 发送报文
    private String startTask(Long id, List<String> ips) {
        System.out.println(jobAddress);
        String res = "";
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("job_id", id);
            map.put("data", ips.toArray());
            res = HttpUtil.post(jobAddress + "/start", JSONUtil.toJsonStr(map));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res;
    }

    /**
     * 批量执行探活,远程执行的结果
     *
     * @param tasks 需要执行探活主键集合 { "job_id":"12222", "data":["222","1345"] }
     * @return 结果
     */
    @Override
    public int updateTask(String tasks) {

        JSONObject req = JSONUtil.parseObj(tasks);
        Integer job_id = req.getInt("job_id");
        JSONArray data = req.getJSONArray("data");

        if (job_id < 0) {
            throw new ServiceException("任务号不能为空");
        }

        Db.tx(() -> {
            Db.update("UPDATE t_detect_job SET job_status = 'off',job_end=? WHERE id = ?", new Date(), job_id);
            if (CollUtil.isNotEmpty(data)) {
                Db.update("UPDATE t_city_ip set address_status = 'sz' WHERE ip_job_id = " + job_id
                        + " AND ip_address_i in (" + data.join(",") + ") ");
            }
            return true;
        });

        return 1;
    }

    private TDetectJob getTDetectJob(List<CitySegment> citySegments) {
        Date date = DateUtil.date();
        String format = DateUtil.format(date, "yyyyMMddhhmmss");
        TDetectJob job = new TDetectJob();
        job.setJobNo("job-" + format);
        job.setJobStart(new Date());
        job.setJobStatus("on");

        return job;
    }

    @Transactional
    @Override
    public int joball() {
        CitySegment dao = new CitySegment().dao();
        Record record = Db.findFirst("select 1 from t_detect_job where job_status = 'on'");
        if (record != null) {
            throw new IllegalArgumentException("探活任务正在执行，不能重复执行！");
        }
        List<CitySegment> csList = dao
                .find("select * from t_city_segment ");

        TDetectJob tDetectJob = getTDetectJob(csList);
        this.insertTDetectJob(tDetectJob);
        List<TDetectJobSegment> tDetectJobSegmentList = new ArrayList<>();
        List<String> ips = new ArrayList<>();

        for (CitySegment cs : csList) {
            TCityIp tCityIp = new TCityIp();
            tCityIp.setIpJobId(tDetectJob.getId());
            tCityIp.setIpJobNo(tDetectJob.getJobNo());
            tCityIp.setIpSegmentId(cs.getId());
            tCityIpMapper.updateTCityIpByJob(tCityIp);

            TDetectJobSegment tDetectJobSegment = new TDetectJobSegment();
            BeanUtils.copyProperties(cs, tDetectJobSegment, "id");
            tDetectJobSegment.setJobId(tDetectJob.getId());
            tDetectJobSegmentList.add(tDetectJobSegment);

            ips.add(cs.getIpStartI() + "-" + cs.getIpEndI());
        }
        tDetectJob.setTDetectJobSegmentList(tDetectJobSegmentList);
        int i = this.updateTDetectJob(tDetectJob);

        // 转发给任务
        // 调用接口，传入ips
        String msg = startTask(tDetectJob.getId(), ips);
        if (!msg.contains("200")) {
            tDetectJob.setJobStatus("off");
            this.updateTDetectJob(tDetectJob);
//			throw new ServiceException("未成功！");
        }
        return i;
    }
}
